/**
 * @class   wosh::building::Appliance
 * @brief   BuildingObject representing a generic (real) appliance.
 *          This class provides standard Methods and properties to 
 *          control the mapped wosh::interfaces::devices::Switch or 
 *          wosh::interfaces::devices::Dimmer
 *          wosh::building::Appliance is usually a child of wosh::building::Room
 *
 ****************************************************************************
 * @version 0.8.399 $Id: Appliance.h 2882 2010-08-09 11:08:30Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Building_Appliance_H__
 #define __WOSH_Building_Appliance_H__

 #include <framework/building/BuildingObject.h>

 #include <interfaces/devices/Switch.h>
 #include <interfaces/devices/Dimmer.h>


namespace wosh {
 namespace building {

 #define _Appliance_VERSION					0.900

 #define _Appliance_KEY_PowerWatt			"PowerWatt"
 #define _Appliance_KEY_ExternalAppliance	"ExternalAppliance"
 #define _Appliance_KEY_Level				"Level"

 #define _Appliance_METHOD_on				"turn_on"
 #define _Appliance_METHOD_off				"turn_off"
 #define _Appliance_METHOD_dim				"dim"
 #define _Appliance_METHOD_bright			"bright"
 #define _Appliance_METHOD_fade				"fade"

 #define _Appliance_METHOD_updatedchildren	"updatedchildren"


class Appliance : public BuildingObject
 {
	WOSH_BUILDINGOBJECT(wosh::building::Appliance)

	public:
		/**
		 * @brief   appliance states
		 */
		enum APPLIANCE_STATE {
			APPLIANCE_OFF		= 0,	///< appliace is off
			APPLIANCE_ON		= 100,	///< appliace is on
			APPLIANCE_FADED		= 101,	///< appliace is on, but not at maximum level
			APPLIANCE_UNKNOWN	= 102	///< appliace state is unknown
		};

	public:
		/**
		 * @brief  Empty constructor.
		 */
		Appliance();
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Appliance( const Appliance& m ) : BuildingObject(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Appliance() { }


	public:
		virtual void busMessageChild( const Message& message );

//@}
/** @name Appliance Interface - 
 * @{
 ******************************************************************************/
	public:
		virtual WRESULT turnOn()						{ return mmDoTurnOn(NULL);}
		virtual WRESULT turnOff()						{ return mmDoTurnOff(NULL);}
		virtual WRESULT turn( int dimvalue, const SecurityToken* security = NULL );
		virtual WRESULT dim( int value, const SecurityToken* security = NULL );
		virtual WRESULT bright( int value, const SecurityToken* security = NULL );

		inline bool isOn() const						{ return (this->level > 0); }
		inline bool isOff() const						{ return (this->level == 0); }

	public:
		virtual std::string getMainSwitchName() const	{ return getChildByInterface(wosh::interfaces::devices::Switch::bundleType()); }

		/**
		 * @brief   Get last known appliance state (opened, closed, unknown)
		 * @return  current appliance state (enum)
		 */
		Appliance::APPLIANCE_STATE getState() const		{ return this->state; }
		/**
		 * @brief   Get appliance state as a literal string
		 * @return  current appliance state as literal string
		 */
		inline const char* getStateAsString() const		{ return getStateAsString(this->state); }
		/**
		 * @brief   Get appliance state as a literal string
		 * @param state [in] appliance state to be retrieved as literal string
		 * @return  passed appliance state as literal string
		 */
		static const char* getStateAsString( Appliance::APPLIANCE_STATE state );
		/**
		 * @brief   Get appliance state from a literal string
		 * @param state [in] appliance state as literal string
		 * @return  appliance state (as enum) associated with the argument 
		 */
		static Appliance::APPLIANCE_STATE getStateFromString( const char* state );

//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		virtual bool updateHash( DataHashContext* hash_context ) const;
//@}
	private:
		WRESULT mmDoTurnOn( const SecurityToken* security );
		WRESULT mmDoTurnOff( const SecurityToken* security );

		Response* mmDoFade( const Message* requestMessage );
		Response* mmDoDim( const Message* requestMessage );
		Response* mmDoBright( const Message* requestMessage );

	protected:
		virtual void init();
		void setState( Appliance::APPLIANCE_STATE state, int level = -1, bool raiseEvent = true, const SecurityToken* source_token = NULL );

	protected:
		/// level as enum, fade level is saved in Properties[_Appliance_KEY_Level] and level field
		Appliance::APPLIANCE_STATE state;
		int level; ///< Properties[_Appliance_KEY_Level] is shadow var


}; // class def



/**
 * @class   wosh::building::Appliance_StateChanged
 * @brief   Raised when door state is changed (such as open to closed).
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c appliance_state [Variant::INTEGER] (always present, first item of the list)
 *  - \c previous_appliance_state (optional, second item of the list)
 *
 * Some getters are provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::building:Appliance
 ****************************************************************************
 * @version 0.8.399 $Id: Appliance.h 2882 2010-08-09 11:08:30Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class Appliance_StateChanged : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::building::Appliance_StateChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		Appliance_StateChanged()
			: wosh::Fact(_BuildingObject_EVENT_StateChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param current_appliance_state [in] current state of the appliance
		 */
		Appliance_StateChanged( Appliance::APPLIANCE_STATE current_appliance_state );
		/**
		 * @brief  Constructor with initializers.
		 * @param current_appliance_state [in] current state of the appliance
		 * @param current_level [in] current level of the appliance
		 */
		Appliance_StateChanged( Appliance::APPLIANCE_STATE current_appliance_state, int current_level );
		/**
		 * @brief  Constructor with initializers.
		 * @param current_appliance_state [in] current state of the appliance
		 * @param current_level [in] current level of the appliance
		 * @param previous_appliance_state [in] previous state of the appliance
		 * @param previous_level [in] previous level of the appliance
		 */
		Appliance_StateChanged( Appliance::APPLIANCE_STATE current_appliance_state, int current_level, Appliance::APPLIANCE_STATE previous_appliance_state, int previous_level );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Appliance_StateChanged( const Appliance_StateChanged& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Appliance_StateChanged() { }

	public:
		/**
		 * @brief   Get appliance state (opened, closed, unknown).
		 * @return  current appliance state (enum)
		 */
		Appliance::APPLIANCE_STATE getApplianceState() const;
		/**
		 * @brief   Get appliance level.
		 * @return  current appliance level (value)
		 */
		int getApplianceLevel() const;

		/**
		 * @brief   Get previous appliance state (opened, closed, unknown).
		 * @return  previous appliance state (enum)
		 */
		Appliance::APPLIANCE_STATE getPreviousApplianceState() const;
		/**
		 * @brief   Get appliance level.
		 * @return  current appliance level (value)
		 */
		int getAppliancePreviousLevel() const;

		inline bool isOn() const				{ return (getApplianceLevel() > 0); }
		inline bool isOff() const				{ return (getApplianceLevel() == 0); }

}; // class def


 }; // namespace building
}; // namespace wosh

#endif //__WOSH_Building_Appliance_H__
